import pandas
import numpy as np
import scipy.stats as stats
from sklearn import manifold
import matplotlib.pyplot as plt


def dimension_reduction(np_array, d=2):
    """
    使用TSNE降为二维，以便可视化
    :param np_array:
    :param d:
    :return:
    """
    tsne = manifold.TSNE(n_components=d, init='pca', random_state=1)
    transformed_dataset = tsne.fit_transform(np_array)
    return transformed_dataset


def show_2d_fig(np_2d_array):
    plt.scatter(np_2d_array[:, 0], np_2d_array[:, 1])
    plt.show()
    pass


def t_estimate_u_interval(samples, confidence=0.95):
    """
    基于t分布使用样本估计总体的均值置信区间
    :param samples: 样本（一维numpy数组）
    :param confidence: 置信度
    :return: 返回95%置信度的区间
    """
    mean = np.mean(samples)  # 求样本的均值
    s = np.std(samples, ddof=1)  # 求样本的标准差（无偏）
    scale = s / (samples.size ** 0.5)  # 求样本均值对应的标准差估计
    # 应用t分布使用样本估计总体的均值，使用了快捷方法，也可以使用PPF函数求上下界
    inter = stats.t.interval(alpha=confidence, df=samples.size - 1, loc=mean, scale=scale)
    return inter


def chi2_estimate_sigma_interval(samples, confidence=0.95):
    """
    基于chi2分布使用样本估计总体的标准差置信区域
    :param samples: 样本（一维numpy数组）
    :param confidence: 置信度
    :return: 返回置信度下的标准差估计区间
    """
    s = np.std(samples, ddof=1)  # 求样本的标准差（无偏）
    n = samples.size
    lower = stats.chi2.ppf((1 - confidence) / 2, n - 1)  # lower percentile
    upper = stats.chi2.ppf(1 - (1 - confidence) / 2, n - 1)  # upper percentile
    # 应用chi分布使用样本估计总体的标准差区间
    inter = (np.sqrt((n - 1) / upper) * s, np.sqrt((n - 1) / lower) * s)
    return inter


if __name__ == '__main__':
    data = np.random.randn(100, 10)
    print(data.shape)
    d2 = dimension_reduction(data, d=2)
    print(d2.shape)
    d3 = dimension_reduction(data, d=3)
    print(d3.shape)
    show_2d_fig(d2)
